package com.newly.center.sys.service.role.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.newly.center.sys.service.authEntity.api.IAuthEntityService;
import com.newly.center.sys.service.tenant.api.ITenantService;
import com.newly.common.base.constants.AuthConstant;
import com.newly.common.base.entity.sys.auth.role.bo.RoleTypeBo;
import com.newly.common.base.entity.sys.auth.role.dto.RoleDto;
import com.newly.common.base.entity.sys.auth.role.po.RolePo;
import com.newly.common.base.entity.sys.auth.role.po.TenantRolePo;
import com.newly.common.base.entity.sys.tenant.bo.SimpleTenantBo;
import com.newly.common.mapper.sys.RoleMapper;
import com.newly.common.mapper.sys.TenantRoleMapper;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @program: newly-parent
 * @remark: 角色业务基类
 * @author: guan
 * @create: 2021-12-23 05:03
 */
public abstract class AbstractRoleService {

    @Autowired
    protected TenantRoleMapper tenantRoleMapper;

    @Autowired
    protected ITenantService tenantService;

    @Autowired
    protected RoleMapper roleMapper;

    @Autowired
    protected IAuthEntityService authEntityService;


    protected List<RolePo> selectByTenantIds(List<Long> tenantIds) {
        if (ObjectUtil.isEmpty(tenantIds)) return null;
        LambdaQueryWrapper<TenantRolePo> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(TenantRolePo::getUserId, tenantIds);
        List<TenantRolePo> tenantRolePos = tenantRoleMapper.selectList(wrapper);
        if (!ObjectUtil.isEmpty(tenantRolePos)) {
            List<Integer> roleIds = tenantRolePos.stream()
                    .map(tenantRolePo -> tenantRolePo.getRoleId()).collect(Collectors.toList());
            return this.selectByIds(roleIds);
        }
        return null;
    }

    protected List<RolePo> selectByIds(List<Integer> roleIds) {
        if (ObjectUtil.isEmpty(roleIds)) return null;
        LambdaQueryWrapper<RolePo> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(RolePo::getId, roleIds);
        wrapper.eq(RolePo::getEnable, AuthConstant.Enable.OPEN.getCode());
        return roleMapper.selectList(wrapper);
    }

    protected Integer insert(RoleDto roleDto) {
        if (ObjectUtil.isEmpty(roleDto)) return null;

        RolePo rolePo = BeanUtil.copyProperties(roleDto, RolePo.class);
        rolePo.setAuth(roleDto.getAuth());
        DateTime dateTime = DateUtil.date();
        rolePo.setCreateTime(dateTime);
        rolePo.setUpdateTime(dateTime);
        if (ObjectUtil.isEmpty(roleDto.getType())) {
            rolePo.setType(AuthConstant.RoleType.CLIENT.getCode());
        }
        if (ObjectUtil.isEmpty(roleDto.getLevel())) {
            rolePo.setLevel(0);
        }

        int result = roleMapper.insert(rolePo);
        if (result > 0) {
            return rolePo.getId();
        }
        return null;
    }

    protected IPage<RolePo> selectPage(Integer offset, Integer limit, LambdaQueryWrapper<RolePo> wrapper) {
        if (ObjectUtil.isEmpty(offset) || ObjectUtil.isEmpty(limit)) return null;
        return roleMapper.selectPage(new Page<>(offset, limit), wrapper);
    }


    public List<Integer> parseIds(List<RolePo> rolePos) {
        if (ObjectUtil.isEmpty(rolePos)) return null;
        return rolePos.stream().map(rolePo -> rolePo.getId()).distinct()
                .collect(Collectors.toList());
    }

    protected int deleteByIds(List<Integer> roleIds) {
        if (ObjectUtil.isEmpty(roleIds)) return 0;
        int batchIds = roleMapper.deleteBatchIds(roleIds);
        if (batchIds > 0) {
            // 删除租户与角色关联关系
            LambdaQueryWrapper<TenantRolePo> tenantRoleWrapper = new LambdaQueryWrapper<>();
            tenantRoleWrapper.in(TenantRolePo::getRoleId, roleIds);
            tenantRoleMapper.delete(tenantRoleWrapper);
            // 删除权限实体
            authEntityService.removeByRoleIds(roleIds);
        }
        return batchIds;
    }

    protected List<RolePo> selectByParentIds(List<Integer> parentRoleIds) {
        if (ObjectUtil.isEmpty(parentRoleIds)) return null;
        LambdaQueryWrapper<RolePo> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(RolePo::getParentId, parentRoleIds);
        return roleMapper.selectList(wrapper);
    }


    protected int updateById(RolePo rolePo) {
        if (ObjectUtil.isEmpty(rolePo)) return 0;
        return roleMapper.updateById(rolePo);
    }

    protected int updateById(RoleDto roleDto) {
        if (ObjectUtil.isEmpty(roleDto)) return 0;
        return updateById(BeanUtil.copyProperties(roleDto, RolePo.class));
    }


    public void setProperties(RolePo rolePo) {
        if (ObjectUtil.isEmpty(rolePo)) {
            return;
        }
        // 设置租户
        SimpleTenantBo simpleTenantBo = tenantService.getSimpleTenant(rolePo.getCreateBy());
        if (!ObjectUtil.isEmpty(simpleTenantBo)) {
            rolePo.setCreateTenant(simpleTenantBo);
        }
        // 设置权限
//        List<PermPo> permPos = permService.getByRoleId(rolePo.getId());
//        if (!ObjectUtil.isEmpty(permPos)) {
//            rolePo.setPerms(permPos);
//        }
        // 设置角色类型
        rolePo.setRoleType(getType(rolePo.getType()));
    }


    protected List<Long> parseTenantIds(List<RolePo> rolePos) {
        if (ObjectUtil.isEmpty(rolePos)) return null;
        return rolePos.stream().map(rolePo -> rolePo.getCreateBy()).distinct()
                .collect(Collectors.toList());
    }


    public List<RoleTypeBo> getTypes() {
        AuthConstant.RoleType[] values = AuthConstant.RoleType.values();
        List<RoleTypeBo> roleTypeBos = new ArrayList<>(values.length);
        for (AuthConstant.RoleType value : values) {
            roleTypeBos.add(new RoleTypeBo(value));
        }
        return roleTypeBos;
    }

    protected RoleTypeBo getType(Integer type) {
        if (ObjectUtil.isEmpty(type)) return null;
        for (RoleTypeBo roleTypeBo : getTypes()) {
            if (type.equals(roleTypeBo.getCode())) {
                return roleTypeBo;
            }
        }
        return null;
    }


}
